from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from econ_analysis.models import FishingImpactAnalysisMap
from utilities import nc_constants, GetSpeciesByGroup, GetPortsByGroup, ensure_proper_name
from ImpactAnalysis import AnalysisResult, EmptyAnalysisResult

'''    
Caches analysis results (by running analysis) on all MPAs owned/shared by the given Users/Groups
Called by views.adminUserAnalysis and views.adminGroupAnalysis
'''
def process_group_mpas(group_ids):
    from utilities import get_group_mpas
    mpa_lists = get_group_mpas(group_ids)
 
    #run analysis for all fishing groups on each mpa in each mpa list
    fishing_groups = nc_constants.GROUPS.values()
    for owner, mpa_list in mpa_lists.items():
        for mpa in mpa_list:
            for group in fishing_groups:
                get_mpa_results(mpa, group)
    return mpa_lists.keys() 
    
'''    
Caches analysis results (by running analysis) on all MPAs owned/shared by the given Users/Groups
Called by views.adminUserAnalysis and views.adminGroupAnalysis
'''
def process_user_mpas(user_ids):
    from utilities import get_user_mpas
    mpa_lists = get_user_mpas(user_ids) 
 
    #run analysis for all fishing groups on each mpa in each mpa list
    fishing_groups = nc_constants.GROUPS.values()
    for owner, mpa_list in mpa_lists.items():
        for mpa in mpa_list:
            for group in fishing_groups:
                get_mpa_results(mpa, group)
    return mpa_lists.keys()     
    
  
'''
Renders template with embedded analysis results
Called from views.impact_analysis 
'''
def display_mpa_analysis(request, mpa, group, port=None, template='impact_analysis.html'):
    mpa_results = get_mpa_results(mpa, group, port)
    #not sure that the following try/except logic is really appropriate, but I hesitate to remove it 
    try:
        #if get_mpa_results threw an error it will return a response object of some sort
        if mpa_results.status_code:
            response_object = mpa_results
            return response_object
    except:
        #otherwise it worked 
        return render_to_response(template, RequestContext(request, {'mpa':mpa, 'all_results': mpa_results}))  
      
'''
Returns a list of AnalysisResults for given mpa cache, group, and port
Called from get_mpa_results 
'''         
def construct_port_results(cache, group, single_port):
    port_results = []
    results = list(cache)
    for result in results:
        port_results.append(AnalysisResult(id=result.mpa_id, type='mpa', group=group, port=single_port, species=result.species, percOverallArea=result.perc_area, percOverallValue=result.perc_value))
    return port_results       
 
'''  
Returns a list of port results (itself a list of species results) for the given mpa
Called from process_group_mpas, process_user_mpas, display_mpa_analysis, and ArrayAnalysis.compile_array_results 
'''  
def get_mpa_results(mpa, group, port=None):
    from AnalysisCache import get_mpa_cache, cache_analysis_results
    from ImpactAnalysis import Analysis
    group = ensure_proper_name(group)
    mpa_results = []
    if port is None:
        ports = GetPortsByGroup(group)
    else:
        ports = [port]
    
    #Get and compile list of results for each port
    for single_port in ports:  
        #checking cache for results
        mpa_cache = get_mpa_cache(mpa, group, single_port)
        #if there is available cache
        if len(mpa_cache) > 0:
            port_results = construct_port_results(mpa_cache, group, single_port)
            #cache results if this particular mpa has not already been cached (might have been an mpa with identical geom)
            cache_analysis_results(port_results, group, mpa, port=single_port)
        #otherwise (if no cache is available), 
        #or if mpas are out of date (original cache), or have different allowed uses or changed geometry (new cache)
        else:           
            #Get all maps from the group and port that we want to analyze
            maps = FishingImpactAnalysisMap.objects.getSubset(group, single_port)
            port_results = []
            if len(maps) > 0:
                #run the analysis
                analysis = Analysis()
                port_results = analysis.run(mpa, maps)
                #Cache analysis results 
                cache_analysis_results(port_results, group, mpa, port=single_port)
            
        #Expand results to include those species that exist within the group but not within this port (denoted with '---')
        port_results = flesh_out_results(group, single_port, port_results)

        #sort results alphabetically by species name
        port_results.sort(key=lambda obj: obj.species)
                
        mpa_results.append(port_results)
    return mpa_results
  
'''
Compiles mpa results 
Returns rendering results for given mpa and fishing group
Note:  This assumes an existing cache for the given mpa and user_group
Called from views.print_report
'''     
def print_mpa_report(request, mpa, user_group, template='printable_mpa_report.html'):
    from AnalysisCache import get_mpa_cache
    ports = GetPortsByGroup(user_group)
    all_results = []
    for single_port in ports:
        #grab the cached results
        cache = get_mpa_cache(mpa, user_group, single_port)
        results = list(cache)
        
        #create an AnalysisResult instance for each cached result
        analysis_results = []
        for result in results:
            analysis_results.append(AnalysisResult(id=result.mpa_id, type='mpa', group=user_group, port=single_port, species=result.species, percOverallArea=result.perc_area, percOverallValue=result.perc_value))
        
        #expand analysis results to include species that may belong to this group, but are not relevant for this port
        analysis_results = flesh_out_results(user_group, single_port, analysis_results)
        
        #sort results alphabetically by species name
        analysis_results.sort(key=lambda obj: obj.species)
        
        #adjust recreational Fort Bragg display
        if user_group in ['Recreational Dive', 'Recreational Kayak', 'Recreational Private Vessel']:
            for result in analysis_results:
                if result.port == 'Fort Bragg':
                    result.port = 'Fort Bragg / Albion'
        
        all_results.append(analysis_results)
    
    return render_to_response(template, RequestContext(request, {'mpa':mpa, 'user_group':user_group, 'all_results':all_results})) 
      
    
'''
Fills out analysis results with species that are relevant for the given group, but not yet present in the results
Called by display_mpa_analysis, get_mpa_results, and print_mpa_report
'''
def flesh_out_results(group, port, results):
    from utilities import isCOM, isSWD
    group_species = GetSpeciesByGroup(group)
    result_species = [result.species for result in results]
    missing_species = [specs for specs in group_species if specs not in result_species]
    for spec in missing_species:
        results.append(EmptyAnalysisResult(group, port, spec, 'mpa'))
    if isCOM(group):
        results = adjust_commercial_species(results)
    if isSWD(group):
        for result in results:
            result.species = 'Seaweed (Hand Harvest)'
    return results
     
'''
Modifies commercial species for appropriate display:
Species Name(s) (Catch Method)
Called by flesh_out_results
'''
def adjust_commercial_species(results):
    species_dict = nc_constants.COMMERCIAL_SPECIES_DISPLAY
    for result in results:
        result.species = species_dict[result.species]
    return results
      
      